/*
 * Copyright 2007-2009 Thomas Krause (thomas@berlin-reloaded.de)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.gidoo.cms.admin;

import java.util.ArrayList;
import java.util.Locale;
import java.util.Properties;
import javax.jcr.RepositoryException;
import org.gidoo.cms.admin.addins.AddInPanel;
import org.gidoo.cms.admin.addins.SectionsPanel;
import org.gidoo.cms.admin.addins.SingleUserPanel;
import org.gidoo.cms.admin.addins.UsersPanel;
import org.gidoo.cms.login.GidooCMSSession;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import org.apache.wicket.Component;
import org.apache.wicket.ResourceReference;
import org.apache.wicket.ajax.IAjaxIndicatorAware;
import org.apache.wicket.authorization.strategies.role.Roles;
import org.apache.wicket.authorization.strategies.role.annotations.AuthorizeInstantiation;
import org.apache.wicket.extensions.ajax.markup.html.AjaxIndicatorAppender;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.markup.html.tree.BaseTree;
import org.apache.wicket.markup.html.tree.ITreeStateListener;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.ResourceModel;
import org.gidoo.cms.GidooCMS;
import org.gidoo.cms.IAdminPlugin;
import org.gidoo.cms.admin.addins.BackupPanel;
import org.gidoo.cms.admin.addins.SingleSectionPanel;
import org.gidoo.cms.helper.AdminNavPanel;
import org.apache.wicket.markup.html.CSSPackageResource;
import org.apache.wicket.markup.html.PackageResource;

@AuthorizeInstantiation(Roles.ADMIN)
/**
 * This page is the container for all administrative actions.
 * @author <a href="mailto:thomas@berlin-reloaded.de">Thomas Krause</a>
 */
public class AdminPage extends WebPage implements ITreeStateListener, IAjaxIndicatorAware
{

  public static final ResourceReference CSS_ADMIN =
    new ResourceReference(AdminPage.class, "admin.css");
  private BaseTree treeNav;
  private DefaultTreeModel treeNavModel;
  private Panel panelAddIn;
  private DefaultMutableTreeNode rootNode;
  private DefaultMutableTreeNode userNode;
  private DefaultMutableTreeNode sectionNode;
  private DefaultMutableTreeNode backupNode;
  private DefaultMutableTreeNode selectedNode;
  private ArrayList<DefaultMutableTreeNode> addins;
  private final AjaxIndicatorAppender indicatorAppender = new AjaxIndicatorAppender();

  /** Creates a new instance of AdminPage */
  public AdminPage()
  {
    add(CSSPackageResource.getHeaderContribution(CSS_ADMIN));
    add(indicatorAppender);

    add(new Label("lblTitle", new ResourceModel("administration")));
    createTree();
    panelAddIn = new AddInPanel("panelAddIn");
    add(panelAddIn);
    add(new AdminNavPanel("panelAdminNav", AdminPage.class));

    add(new Link("lnkLogout")
    {

      public void onClick()
      {
        ((GidooCMSSession) this.getSession()).signOut();
        this.setResponsePage(((GidooCMS) getApplication()).getHomePage());
      }
    });
  }

  private void createTree()
  {
    rootNode = new DefaultMutableTreeNode("root");

    userNode = new DefaultMutableTreeNode( getString("user"));
    sectionNode = new DefaultMutableTreeNode(getString("section"));
    backupNode = new DefaultMutableTreeNode(getString("backup"));

    rootNode.add(userNode);
    rootNode.add(sectionNode);
    rootNode.add(backupNode);

    addins = new ArrayList<DefaultMutableTreeNode>();

    for(IAdminPlugin a : ((GidooCMS) getApplication()).CMS_CONFIGURATION.getAdminPlugins())
    {
      DefaultMutableTreeNode n = new DefaultMutableTreeNode(a, false);
      addins.add(n);
      rootNode.add(n);
    }

    treeNavModel = new DefaultTreeModel(rootNode);
    treeNav = new BaseTree("treeNav", new Model(treeNavModel))
    {

      protected Component newNodeComponent(String id, IModel model)
      {
        return new TreePanel(id, model, treeNav, userNode, sectionNode, backupNode);
      }
    };

    add(treeNav);

    treeNav.setRootLess(true);
    treeNav.getTreeState().collapseAll();
    treeNav.getTreeState().setAllowSelectMultiple(false);
    treeNav.getTreeState().addTreeStateListener(this);
    updateTreeModel(null, null);
  }

  public void updateDataAndView()
  {
    try
    {
      reloadAddin();

      if(selectedNode != null)
      {
        if(selectedNode == userNode)
        {
          updateTreeModel(null, null);
          treeNav.getTreeState().selectNode(selectedNode, true);
        }
        else if(selectedNode == sectionNode)
        {
          updateTreeModel(null, null);
          treeNav.getTreeState().selectNode(sectionNode, true);
        }
        else if(selectedNode == backupNode)
        {
          updateTreeModel(null, null);
          treeNav.getTreeState().selectNode(backupNode, true);
        }
        else if(selectedNode.getUserObject() instanceof Node)
        {
          Node n = (Node) selectedNode.getUserObject();

          if("users".equals(n.getParent().getName()))
          {
            updateTreeModel(n.getName(), null);
          }
          else if("sections".equals(n.getParent().getName()))
          {
            updateTreeModel(null, n.getName());
          }
          else
          {
            updateTreeModel(null, null);
          }
        }
      }
      else
      {
        updateTreeModel(null, null);
      }
    }
    catch(RepositoryException ex)
    {
      Logger.getLogger(AdminPage.class.getName()).log(Level.SEVERE, null, ex);
      error(getString("jcrerror"));
    }
  }

  /** Updates the model (all changeable items) of the navigation tree. */
  public void updateTreeModel(String userToSelect, String sectionToSelect)
  {
    try
    {
      userNode.removeAllChildren();
      sectionNode.removeAllChildren();

      Node jcrRoot = ((GidooCMSSession) getSession()).getJcrRootNode();
      Node jcrUsers = jcrRoot.getNode("users");
      NodeIterator itUsers = jcrUsers.getNodes();

      while(itUsers.hasNext())
      {
        Node u = itUsers.nextNode();
        DefaultMutableTreeNode cur = new DefaultMutableTreeNode(u.getName());

        userNode.add(cur);
        if(u.getName().equals(userToSelect))
        {
          treeNav.getTreeState().selectNode(cur, true);
        }
      }

      Node jcrSections = jcrRoot.getNode("sections");
      NodeIterator itSections = jcrSections.getNodes();

      while(itSections.hasNext())
      {
        Node s = itSections.nextNode();
        DefaultMutableTreeNode cur = new DefaultMutableTreeNode(s.getName());
        sectionNode.add(cur);
        if(s.getName().equals(sectionToSelect))
        {
          treeNav.getTreeState().selectNode(cur, true);
        }
      }

      if(treeNavModel != null)
      {
        treeNavModel.reload();
      }
    }
    catch(RepositoryException ex)
    {
      Logger.getLogger(AdminPage.class.getName()).log(Level.SEVERE, null, ex);
      error(getString("jcrerror"));
    }
  }

  private void reloadAddin() throws RepositoryException
  {
    if(selectedNode == null)
    {
      panelAddIn = new AddInPanel("panelAddIn");
      replace(panelAddIn);
    }
    else if(selectedNode == userNode)
    {
      panelAddIn = new UsersPanel("panelAddIn", this);
      replace(panelAddIn);
    }
    else if(selectedNode == sectionNode)
    {
      panelAddIn = new SectionsPanel("panelAddIn", this);
      replace(panelAddIn);
    }
    else if(selectedNode == backupNode)
    {
      panelAddIn = new BackupPanel("panelAddIn", this);
      replace(panelAddIn);
    }
    else if(selectedNode.getParent() == userNode)
    {
      panelAddIn = new SingleUserPanel("panelAddIn", (String) selectedNode.getUserObject(), this);
      replace(panelAddIn);
    }
    else if(selectedNode.getParent() == sectionNode)
    {
      panelAddIn =
        new SingleSectionPanel("panelAddIn", (String) selectedNode.getUserObject(), this);
      replace(panelAddIn);
    }
    else if(selectedNode.getUserObject() instanceof IAdminPlugin)
    {
      IAdminPlugin p = (IAdminPlugin) selectedNode.getUserObject();
      panelAddIn = p.getPluginPanel("panelAddIn");
      replace(panelAddIn);
    }
    else
    {
      panelAddIn = new AddInPanel("panelAddIn");
      replace(panelAddIn);
      error(getString("novalidselection"));
    }
  }

  public DefaultMutableTreeNode getSelectedNode()
  {
    return selectedNode;
  }

  public void setSelectedNode(DefaultMutableTreeNode selectedNode)
  {
    this.selectedNode = selectedNode;
  }

  public DefaultMutableTreeNode getSectionNode()
  {
    return sectionNode;
  }

  public BaseTree getTreeNav()
  {
    return treeNav;
  }

  /* ITreeStateListener functions */
  @Override
  public void allNodesCollapsed()
  {
  }

  @Override
  public void allNodesExpanded()
  {
  }

  @Override
  public void nodeCollapsed(Object node)
  {
  }

  @Override
  public void nodeExpanded(Object node)
  {
  }

  @Override
  public void nodeSelected(Object node)
  {
    selectedNode = (DefaultMutableTreeNode) node;

    try
    {
      reloadAddin();
    }
    catch(RepositoryException ex)
    {
      Logger.getLogger(AdminPage.class.getName()).log(Level.SEVERE, null, ex);
      error(getString("jcrerror"));
    }
    setResponsePage(this);
  }

  @Override
  public void nodeUnselected(Object node)
  {
    selectedNode = null;

    try
    {
      reloadAddin();
    }
    catch(RepositoryException ex)
    {
      Logger.getLogger(AdminPage.class.getName()).log(Level.SEVERE, null, ex);
      error(getString("jcrerror"));
    }

    setResponsePage(this);
  }

  public String getAjaxIndicatorMarkupId()
  {
    return indicatorAppender.getMarkupId();
  }

}

